package com.sirun.ble.utils;

import android.content.Context;
import android.content.res.AssetManager;

import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author : hzw
 */
public class AwByteUtil {

    /**
     * 将两个byte数组合并为一个
     * @param data1  要合并的数组1
     * @param data2  要合并的数组2
     * @return 合并后的新数组
     */
    public static byte[] mergeBytes(byte[] data1, byte[] data2) {
        byte[] data3 = new byte[data1.length + data2.length];
        System.arraycopy(data1, 0, data3, 0, data1.length);
        System.arraycopy(data2, 0, data3, data1.length, data2.length);
        return data3;
    }

    /**
     * 插入byte, 返回新byte[]
     * @param original
     * @param index
     * @param element
     * @return
     */
    public static byte[] insertByte(byte[] original, int index, byte element) {
        byte[] newArray = new byte[original.length + 1];
        System.arraycopy(original, 0, newArray, 0, index);
        newArray[index] = element;
        System.arraycopy(original, index, newArray, index + 1, original.length - index);
        return newArray;
    }

    /**
     * 插入byte, 修改原始byte[]返回
     * @param original
     * @param index
     * @param element
     */
    public static void insertByteOrigin(byte[] original, int index, byte element) {
        byte[] newArray = new byte[original.length + 1];
        System.arraycopy(original, 0, newArray, 0, original.length);
        newArray[index] = element;
    }

    /**
     * 截取指定下标直接的byte数组
     * @param original
     * @param startIndex
     * @param endIndex
     * @return
     */
    public static byte[] getSpecLengthBytes(byte[] original, int startIndex, int endIndex) {
        return Arrays.copyOfRange(original, startIndex, endIndex);
    }

    /**
     * 补0到指定长度的byte数组
     * @param original
     * @param newLength
     * @return
     */
    public static byte[] add0ToStart(byte[] original, int newLength) {
        if(original.length < newLength) {
            byte[] newBytes = new byte[newLength];
            System.arraycopy(original, 0, newBytes, newLength - original.length, original.length);
            return newBytes;
        } else {
            return getSpecLengthBytes(original, 0, newLength);
        }
    }

    /**
     * 从assets或SD读取文件转为byte
     * @param context
     * @param groupPath
     * @param filename
     * @return
     */
    public static byte[] convertByteFromAssetsOrFile(Context context, String groupPath, String filename){
        byte[] buffer = null;
        AssetManager am = context.getAssets();
        try {
            InputStream inputStream = null;
            if (groupPath != null) {
                inputStream = am.open(groupPath + "/" + filename);
            } else {
                inputStream = am.open(filename);
            }

            int length = inputStream.available();
            buffer = new byte[length];
            inputStream.read(buffer);
        }catch (Exception exception){
            exception.printStackTrace();
        }
        return buffer;
    }

    /**
     * 拆分数组
     * @param array
     * @param chunkSize
     * @return
     *
     * Example usage:
     * int[] numbers = {1, 2, 3, 4, 5, 6, 7};
     * int[][] chunks = chunkArray(numbers, 3);
     * chunks now contains [
     *                       [1, 2, 3],
     *                       [4, 5, 6],
     *                       [7]
     *                     ]
     */
    public static byte[][] chunkArray(byte[] array, int chunkSize) {
        int numOfChunks = (int)Math.ceil((double)array.length / chunkSize);
        byte[][] output = new byte[numOfChunks][];

        for(int i = 0; i < numOfChunks; ++i) {
            int start = i * chunkSize;
            int length = Math.min(array.length - start, chunkSize);

            byte[] temp = new byte[length];
            System.arraycopy(array, start, temp, 0, length);
            output[i] = temp;
        }

        return output;
    }

    /**
     * 将字节 转换为字符串
     *
     * @param src 需要转换的字节数组
     * @return 返回转换完之后的数据
     */
    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
//            BleLog.d("===>bytesToHexString i: " + i + " ,src[i]: " + src[i]
//                    + " ,0xff: " + v + " ,toHexString: " + hv);
        }
        return stringBuilder.toString();
    }
    /**
     * 将字符串转化为16进制的字节数组
     *
     * @param message
     *            需要被转换的字符
     * @return
     */
    public static byte[] getHexBytes(String message) {
        int len = message.length() / 2;
        char[] chars = message.toCharArray();

        String[] hexStr = new String[len];

        byte[] bytes = new byte[len];

        for (int i = 0, j = 0; j < len; i += 2, j++) {
            hexStr[j] = "" + chars[i] + chars[i + 1];
            bytes[j] = (byte) Integer.parseInt(hexStr[j], 16);
        }
        return bytes;
    }

    /**
     * 将Mac地址字符串转换为byte数组
     * @param mac Mac地址字符串，格式如：78:44:fd:c9:87:a0
     * @return 该Mac地址的byte数组形式
     */
    public static byte[] getMacBytes(String mac) {
        byte[] macBytes = new byte[6];

        String[] strArr = mac.split(":");
        for (int i = 0; i < strArr.length; i++) {
            int value = Integer.parseInt(strArr[i], 16);
            macBytes[i] = (byte) value;
        }

        return macBytes;
    }

    /**
     * 16进制字符串转byte数组
     * @param hex
     * @return
     */
    public static byte[] hexStrToBytes(String hex) {
        ByteBuffer bf = ByteBuffer.allocate(hex.length() / 2);
        for (int i = 0; i < hex.length(); i++) {
            String hexStr = hex.charAt(i) + "";
            i++;
            hexStr += hex.charAt(i);
            byte b = (byte) Integer.parseInt(hexStr, 16);
            bf.put(b);
        }
        return bf.array();
    }

    /**
     * 10进制转16进制数组
     * @param decimal
     * @return
     */
    public static byte[] decToHexArray(int decimal) {
        // 转换为16进制字符串
        String hexString = Integer.toHexString(decimal);
        // 创建字节数组，长度为字符串长度的一半（每个字符代表4位）
        byte[] hexBytes = new byte[hexString.length() / 2];
        // 将字符串转换为字节数组
        for (int i = 0; i < hexString.length(); i += 2) {
            // 将两个字符转换为一个字节
            hexBytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i+1), 16));
        }
        return hexBytes;
    }

    /**
     * 16进制转10进制
     * @param hex
     * @return
     */
    public static int hexToDec(String hex) {
        int result = 0;
        for (int i = 0; i < hex.length(); i++) {
            int digit = Character.digit(hex.charAt(i), 16);
            result = result * 16 + digit;
        }
        return result;
    }

    /**
     * 10进制转二进制
     * @param param
     * @return
     */
    public static String decToBinary(int param) {
        //Integer.toBinaryString(param); 不补0
        return toBinaryString(param, 8);
    }

    /**
     * 16进制转2进制
     * @param hex
     * @return
     */
    public static String hexToBinary(String hex) {
        return decToBinary(hexToDec(hex));
    }

    /**
     * 转2进制补足指定位数0
     * @param number
     * @param bitCount
     * @return
     */
    public static String toBinaryString(int number, int bitCount) {
        String binaryString = Integer.toBinaryString(number);
        int paddingCount = bitCount - binaryString.length();
        if (paddingCount > 0) {
            return String.format("%1$0" + paddingCount + "d", 0) + binaryString;
        } else {
            return binaryString;
        }
    }

    /**
     * 10进制格式化为16进制, 如255 输出 "FF
     * @param number
     * @return
     */
    public String formatDecToHexStr(int number) {
        String hexString = String.format("%X", number);
        return hexString; // number 255 输出 "FF"
    }

    /**
     * 16进制字符串转byte数组
     * @param hexString
     * @return
     */
    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length();
        if (length % 2 != 0) {
            hexString = "0" + hexString; // 如果是奇数，补一个0
            length = length + 1;
        }
        byte[] byteArray = new byte[length / 2]; // 两个字符表示一个字节
        char[] hexChars = hexString.toCharArray();
        for (int i = 0; i < length; i += 2) {
            byteArray[i / 2] = (byte) ((hexCharToInt(hexChars[i]) << 4) | hexCharToInt(hexChars[i + 1]));
        }
        return byteArray;
    }

    private static int hexCharToInt(char c) {
        if (c >= '0' && c <= '9') {
            return (c - '0');
        } else if (c >= 'A' && c <= 'F') {
            return (c - 'A' + 10);
        } else if (c >= 'a' && c <= 'f') {
            return (c - 'a' + 10);
        } else {
            throw new IllegalArgumentException("Invalid hex char: '" + c + "'");
        }
    }

    /**
     * 按照原数组输出 如0x01 输出01
     * @param bytes
     * @return
     */
    public static String printBytes(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString();
    }


    /**
     * 16进制数组转为 Integer List 集合
     * @param byteArray
     * @return
     */
    public static List<Integer> bytesToIntList(byte[] byteArray) {
        List<Integer> intList = new ArrayList<>();
        for (int i = 0; i < byteArray.length; i += 4) {
            intList.add(ByteBuffer.wrap(byteArray, i, 4).getInt());
        }
        return intList;
    }

    /**
     * 16进制数组转为 Integer List 集合
     * @param byteArray
     * @return
     */
    public static List<Integer> bytesToIntList2(byte[] byteArray) {
        List<Integer> integerList = new ArrayList<>();

        ByteBuffer buffer = ByteBuffer.wrap(byteArray);

        while (buffer.hasRemaining()) {
            integerList.add(buffer.getInt());
        }
        return integerList;
    }

    /**
     * 二进制前高位补0, 如果数据不足length长度，可以通过在前面补零来补全
     * @param number
     * @param length
     * @return
     */
    public static String add0ToBinaryStart(int number, int length) {
        String binaryString = Integer.toBinaryString(number);
        return String.format("%1$" + length + "s", binaryString).replace(' ', '0');
    }

    /**
     * 2进制转16进制字符串
     * @param s
     * @return
     */
    public static String from2To16(String s) {
        //先把2进制转为10进制
        int i = Integer.parseInt(s, 2);
        //再把10进制转为16进制
        return String.format("%16x", i).trim();
    }

    /**
     * byte数组中取int数值，本方法适用于(低位在前，高位在后)的顺序，和和intToBytes（）配套使用
     *
     * @param src
     *            byte数组
     * @param offset
     *            从数组的第offset位开始
     * @return int数值
     */
    public static int bytesToInt(byte[] src, int offset) {
        int value;
        value = (int) ((src[offset] & 0xFF)
                | ((src[offset+1] & 0xFF)<<8)
                | ((src[offset+2] & 0xFF)<<16)
                | ((src[offset+3] & 0xFF)<<24));
        return value;
    }

    /**
     * 将Mac地址的数组形式转换为字符串形式
     * @param macBytes mac地址的数组形式
     * @return Mac地址的字符串，格式如：78:44:fd:c9:87:a0
     */
    public static String getMacString(byte[] macBytes) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < macBytes.length; i++) {
            int v = macBytes[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                builder.append(':').append("0").append(hv);
            } else {
                builder.append(':').append(hv);
            }
//            BleLog.d("===>getMacString i: " + i + " ,macBytes[i]: " + macBytes[i]
//                    + " ,0xff: " + v + " ,toHexString: " + hv);

        }
        return builder.substring(1).toUpperCase();
    }

    /**
     * 判断是否是mac地址
     * https://blog.csdn.net/weixin_39597987/article/details/114232640
     * @param val
     * @return
     */
    public static boolean isMacAddress(String val) {
        if(AwDataUtil.isEmpty(val)) {
            return false;
        }
        String trueMacAddress = "([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}";
        // 这是真正的MAV地址；正则表达式；
        if (val.matches(trueMacAddress)) {
            return true;
        } else {
            return false;

        }

    }

    /**
     * 指定字符串转为mac地址显示
     * @param bleName
     * @return
     */
    public static String getMacStyle(String bleName) {
        if(AwDataUtil.isEmpty(bleName)) {
            return "";
        }
        String temp = bleName.substring(6, bleName.length());
        return convertToMacStyle(temp);
    }

    public static String convertToMacStyle(String s) {
        return s.replaceAll("(.{2})", ":$1").substring(1);
    }

    /**
     * 16进制转字符串
     * @param src
     * @return
     */
    public static String byteToHexString(byte src) {
        StringBuilder stringBuilder = new StringBuilder("");
        int v = src & 0xFF;
        String hv = Integer.toHexString(v);
        if (hv.length() < 2) {
            stringBuilder.append(0);
        }
        stringBuilder.append(hv);
        return stringBuilder.toString();
    }

    /**
     * 16进制字符串转10进制字符串
     * @param hexValue
     * @return
     */
    public static String hexToASCII(String hexValue)
    {
        StringBuilder output = new StringBuilder("");

        for (int i = 0; i < hexValue.length(); i += 2)
        {
            if(i+2<=hexValue.length())
            {
                String str = hexValue.substring(i, i + 2);
                output.append(Integer.parseInt(str, 16));
            }
        }
        return output.toString();
    }

    /**
     * 字节转十六进制
     *
     * @param b 需要进行转换的byte字节
     * @return 转换后的Hex字符串
     */
    public static String byteToHex(byte b) {
        String hex = Integer.toHexString(b & 0xFF);
        if (hex.length() < 2) {
            hex = "0" + hex;
        }
        return hex;
    }

    /**
     * 字节数组转16进制字符串
     * @param bytes 需要转换的byte数组
     * @return  转换后的Hex字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if(hex.length() < 2){
                sb.append(0);
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * Hex字符串转byte
     * @param inHex 待转换的Hex字符串
     * @return  转换后的byte
     */
    public static byte hexToByte(String inHex){
        return (byte)Integer.parseInt(inHex,16);
    }

    /**
     * hex字符串转byte数组
     * @param inHex 待转换的Hex字符串
     * @return  转换后的byte数组结果
     */
    public static byte[] hexToByteArray(String inHex){
        int hexlen = inHex.length();
        byte[] result;
        if (hexlen % 2 == 1){
            //奇数
            hexlen++;
            result = new byte[(hexlen/2)];
            inHex="0"+inHex;
        }else {
            //偶数
            result = new byte[(hexlen/2)];
        }
        int j=0;
        for (int i = 0; i < hexlen; i+=2){
            result[j]=hexToByte(inHex.substring(i,i+2));
            j++;
        }
        return result;
    }

    /**
     * 无符号byte转int
     * @param bytes
     * @param isLittleEndian
     * @return
     */
    public static int byteToInt(byte[] bytes, boolean isLittleEndian) {
        if (bytes == null || bytes.length < 4) {
            throw new IllegalArgumentException("Byte array must be at least 4 bytes long");
        }
        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        buffer.order(isLittleEndian ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
        return buffer.getInt();
    }
}
